package com.smmisia.article.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.smmisia.article.api.AuthService;
import com.smmisia.article.bo.FavoriteBo;
import com.smmisia.article.bo.LikeBo;
import com.smmisia.article.bo.LikeFavoriteBo;
import com.smmisia.article.dto.article.ArticleHotResponse;
import com.smmisia.article.dto.article.ArticleUserDTO;
import com.smmisia.article.dto.article.ArticleUserInfoDTO;
import com.smmisia.article.dto.response.*;
import com.smmisia.article.dto.user.UserVO;
import com.smmisia.article.entity.Article;
import com.smmisia.article.entity.LikeFavorite;
import com.smmisia.article.entity.User;
import com.smmisia.article.entity.UserSignature;
import com.smmisia.article.entity.convetor.ArticleConvertor;
import com.smmisia.article.entity.convetor.UserConvertor;
import com.smmisia.article.exception.customException;
import com.smmisia.article.mapper.ArticleMapper;
import com.smmisia.article.mapper.LikeFavoriteMapper;
import com.smmisia.article.mapper.UserMapper;
import com.smmisia.article.mapper.UserSignatureMapper;
import com.smmisia.article.request.UpdateUserRequest;
import com.smmisia.article.service.UserService;
import com.smmisia.article.utils.BeanUtil;
import com.smmisia.article.utils.LoginUtil;
import com.smmisia.common.Result.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    private final String NUMBERCOUNT = "numbercount:";

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private ArticleMapper articleMapper;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private FollowServiceImpl followServiceImpl;

    @Autowired
    private UserSignatureMapper userSignatureMapper;

    @Autowired
    private LikeFavoriteMapper likeFavoriteMapper;

    @Autowired
    private AuthService authService;


    @Override
    public Result<UserInfoDTO> simpleInfo(Integer id) {
        if (StringUtils.isEmpty(id)) {
            //说明查询的是当前用户信息
            String loginId = (String) StpUtil.getLoginId();
            Integer userId = Integer.valueOf(loginId);
            UserInfoDTO userInfo = getUserInfo(userId);
            return Result.ok(userInfo);
        }
        UserInfoDTO userInfo = getUserInfo(id);
        return Result.ok(userInfo);
    }

    public UserInfoDTO getUserInfo(Integer id) {
        User user = authService.info(id);
        if (user == null) {
            throw new customException("用户不存在");
        }
        UserInfoDTO userInfoDTO = UserConvertor.INSTANCE.mapToUserInfoDTO(user);
        userInfoDTO.setId(user.getId());
        userInfoDTO.setEmail(user.getEmail());
        LambdaQueryWrapper<UserSignature> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserSignature::getUserId, id);
        UserSignature userSignature = userSignatureMapper.selectOne(wrapper);
        if (userSignature == null) {
            userInfoDTO.setSignature(null);
        } else {
            userInfoDTO.setSignature(userSignature.getSignature());
        }
        UserSimpleInfoDTO userSimpleInfoDTO = articleMapper.likedCount(id);
        LikeFollowCountDTO likeFollowCountDTO = followServiceImpl.count(id);
        String mutual = "mutual_follow:user_id:" + id;
        Set<Integer> intersect = redisTemplate.opsForSet().members(mutual);
        if (intersect == null || intersect.isEmpty()) {
            userInfoDTO.setCommonConcern(0);
        }
        List<Integer> idList = intersect.stream().collect(Collectors.toList());
        Integer age = (Integer) redisTemplate.opsForValue().get("age:user_id:" + id);
        if (age == null){
            userInfoDTO.setAge(0);
        }else{
            userInfoDTO.setAge(age);
        }
        String ipAddress = (String) redisTemplate.opsForValue().get("ip:" + id);
        if(org.apache.commons.lang.StringUtils.isEmpty(ipAddress)){
            userInfoDTO.setAddress("未知");
        }else{
            userInfoDTO.setAddress(ipAddress);
        }
        String university = (String) redisTemplate.opsForValue().get("university:user_id:" + id);
        if (university == null){
            userInfoDTO.setUniversity("null");
        }else{
            userInfoDTO.setUniversity(university);
        }

        if(org.apache.commons.lang.StringUtils.isEmpty(userSimpleInfoDTO.getLikeCount())){
            userInfoDTO.setLikeCount(0);
        }else {
            userInfoDTO.setLikeCount(Integer.valueOf(userSimpleInfoDTO.getLikeCount()));
        }
        if(org.apache.commons.lang.StringUtils.isEmpty(userSimpleInfoDTO.getFavoriteCount())){
            userInfoDTO.setFavoriteCount(0);
        }else{
            userInfoDTO.setFavoriteCount(Integer.valueOf(userSimpleInfoDTO.getFavoriteCount()));
        }
        if(org.apache.commons.lang.StringUtils.isEmpty(userSimpleInfoDTO.getArticleCount())){
            userInfoDTO.setArticleCount(0);
        }else{
            userInfoDTO.setArticleCount(Integer.valueOf(userSimpleInfoDTO.getArticleCount()));
        }
        if(likeFollowCountDTO.getFollowCount() == null){
            userInfoDTO.getConcernCount();
        }else{
            userInfoDTO.setConcernCount(likeFollowCountDTO.getFollowCount());
        }
        if(likeFollowCountDTO.getConcernCount() == null){
            userInfoDTO.setVermicelliCount(0);
        }else{
            userInfoDTO.setVermicelliCount(likeFollowCountDTO.getConcernCount());
        }
        if(idList == null){
            userInfoDTO.setCommonConcern(0);
        }else {
            userInfoDTO.setCommonConcern(idList.size());
        }
        return userInfoDTO;
    }

    @Override
    public Result<List<UpDTO>> upInfo() {
        Set<String> userSet = redisTemplate.opsForZSet().reverseRange(NUMBERCOUNT, 0, 4);
        List<Integer> ids = userSet.stream().map(Integer::parseInt).collect(Collectors.toList());
        List<UpDTO> dtos = new LinkedList<>();
        ids.stream().forEach(id -> {
            UpDTO upDTO = new UpDTO();
            User user = userMapper.selectById(id);
            upDTO.setName(user.getUsername());
            UserSignature userSignature = userSignatureMapper.selectById(id);
            upDTO.setSignature(userSignature.getSignature());
            LikeFollowCountDTO dto = followServiceImpl.count(id);
            upDTO.setId(id);
            upDTO.setLikeCount(dto.getLikeCount());
            upDTO.setCommentCount(dto.getFollowCount());//关注
            upDTO.setVisitCount(dto.getConcernCount());//粉丝
            dtos.add(upDTO);
        });

        return Result.ok(dtos);
    }

    @Override
    public Result<List<ArticleUserDTO>> likelist() {
        //获取当前用户id
        String loginId = LoginUtil.getLoginId();
        Integer id = Integer.valueOf(loginId);
        //获取我的点赞总数
        UserSimpleInfoDTO userSimpleInfoDTO = articleMapper.likedCount(id);

        ArticleUserDTO articleUserDTO = new ArticleUserDTO();
        articleUserDTO.setId(id);
        //articleUserDTO.setLikeCount(Integer.valueOf(likeTotal));

        //获取我的收藏总数
        LikeFavoriteBo likeFavoriteBo = likeFavoriteMapper.selectLikeFavoriteById(id);
        Integer favoriteCount = likeFavoriteBo.getFavoriteCount();

        articleUserDTO.setCommentCount(favoriteCount);

        LambdaQueryWrapper<LikeFavorite> queryWrapper = Wrappers.lambdaQuery();

        queryWrapper.eq(LikeFavorite::getUserId, id);
        queryWrapper.eq(LikeFavorite::getLike, 0);

        List<LikeFavorite> likeFavoritesList = likeFavoriteMapper.selectList(queryWrapper);

        //获取点赞文章id集合
        List<Integer> articleIdList = likeFavoritesList.stream().map(LikeFavorite::getArticleId).collect(Collectors.toList());

        List<Article> articleList = articleMapper.selectBatchIds(articleIdList);

        List<ArticleHotResponse> articleHotRespons = articleList.stream().map(article -> {
            ArticleHotResponse dto = ArticleConvertor.INSTANCE.mapToArticleHotResponse(article);
            return dto;
        }).collect(Collectors.toList());

        //获取收藏文章id集合
        LambdaQueryWrapper<LikeFavorite> wrapper = Wrappers.lambdaQuery();

        wrapper.eq(LikeFavorite::getUserId, id);
        wrapper.eq(LikeFavorite::getLike, 1);

        List<LikeFavorite> favoritesList = likeFavoriteMapper.selectList(wrapper);

        //获取收藏文章id集合
        List<Integer> favoriteArticleIdList = favoritesList.stream().map(LikeFavorite::getArticleId).collect(Collectors.toList());

        List<Article> favoriteArticleList = articleMapper.selectBatchIds(favoriteArticleIdList);

        List<ArticleHotResponse> favoriteArticleHotRespons = favoriteArticleList.stream().map(article -> {
            ArticleHotResponse dto = ArticleConvertor.INSTANCE.mapToArticleHotResponse(article);
            return dto;
        }).collect(Collectors.toList());

        //收藏用户id集合
        List<Integer> favoriteUserIdList = articleList.stream().map(Article::getUserId).collect(Collectors.toList());

        List<User> favoriteUserIdListserList = userMapper.selectBatchIds(favoriteUserIdList);

        List<UserResDTO> favoriteUserResDTOS = favoriteUserIdListserList.stream().map(user -> {
            UserResDTO dto = UserConvertor.INSTANCE.mapToUserResDTO(user);
            return dto;
        }).collect(Collectors.toList());


        //点赞用户id集合
        List<Integer> userIdList = articleList.stream().map(Article::getUserId).collect(Collectors.toList());

        List<User> userList = userMapper.selectBatchIds(userIdList);

        List<UserResDTO> userResDTOS = userList.stream().map(user -> {
            UserResDTO dto = UserConvertor.INSTANCE.mapToUserResDTO(user);
            return dto;
        }).collect(Collectors.toList());

        //点赞list
        List<LikeBo> likeBoList = new ArrayList<>();
        LikeBo likeBo = new LikeBo();
        likeBo.setArticleHotResponseList(articleHotRespons);
        likeBo.setUserResDTOList(userResDTOS);
        likeBoList.add(likeBo);
        articleUserDTO.setLikeBoList(likeBoList);

        //收藏list
        List<FavoriteBo> favoriteBoList = new ArrayList<>();
        FavoriteBo favoriteBo = new FavoriteBo();
        favoriteBo.setArticleHotResponseList(favoriteArticleHotRespons);
        favoriteBo.setUserResDTOList(favoriteUserResDTOS);
        favoriteBoList.add(favoriteBo);
        articleUserDTO.setFavoriteBoList(favoriteBoList);


        return Result.ok(articleUserDTO);
    }

    @Override
    public Result<List<UserResDTO>> leaderboard() {
        //TODO 暂时以粉丝数量作为排行榜
        Set<String> userSet = redisTemplate.opsForZSet().reverseRange(NUMBERCOUNT, 0, 4);
        List<Integer> ids = userSet.stream().map(Integer::parseInt).collect(Collectors.toList());

        List<User> users = userMapper.selectBatchIds(ids);

        List<UserResDTO> userResDTOS = users.stream().map(user -> {
            UserResDTO dto = com.smmisia.article.utils.BeanUtil.convert(user, UserResDTO.class);
            return dto;
        }).collect(Collectors.toList());

        return Result.ok(userResDTOS);
    }

    @Override
    public Result<ArticleUserInfoDTO> articleUser() {
        ArticleUserInfoDTO articleUserDTO = new ArticleUserInfoDTO();
        Map<String, Long> userMap = userMapper.selectInfo();
        Map<String, Long> articleMap = articleMapper.selectInfo();
        //总用户数
        Long totalUser = userMap.get("addUser");
        //今日新增
        Long todayAddUser = userMap.get("todayUser");
        //今日新增文章
        Long todayAddArticle = articleMap.get("todayArticle");
        //总文章数
        Long totalArticle = articleMap.get("addArticle");
        articleUserDTO.setTodayAddArticle(todayAddArticle);
        articleUserDTO.setTotalArticle(totalArticle);
        articleUserDTO.setTodayAddUser(todayAddUser);
        articleUserDTO.setTotalUser(totalUser);
        return Result.ok(articleUserDTO);
    }

    @Override
    public void importDBFromExcel10w(List<Map<Integer, String>> dataList) {

    }

    @Override
    public Result<String> getSignature(Integer id) {
        UserSignature userSignature = userSignatureMapper.selectById(id);
        Assert.isNull(userSignature,()-> new RuntimeException("用户签名不存在"));
        return Result.ok(userSignature.getSignature());
    }

    @Override
    public Result<String> updateUserInfo(UpdateUserRequest request) {
        Integer id = StpUtil.getLoginIdAsInt();
        if(request.getAge()!=null){
            redisTemplate.opsForValue().set("age:user_id:" + id,request.getAge());
        }
        if(request.getUniversity()!=null){
            redisTemplate.opsForValue().set("university:user_id:" + id,request.getUniversity());
        }
        if(request.getSignature()!=null){
            UserSignature userSignature = userSignatureMapper.selectById(id);
            if(userSignature==null){
                UserSignature userSignatures = new UserSignature();
                userSignatures.setUserId(id);
                userSignatures.setSignature(request.getSignature());
                userSignatureMapper.insert(userSignatures);
            }else{
                userSignature.setSignature(request.getSignature());
                userSignatureMapper.updateById(userSignature);
            }
        }
        return Result.ok("更新成功");
    }

    /**
     * 获取用户基本信息
     */
    public UserVO getUserInfoByUserId(Integer id) {
        User user = authService.info(id);
        UserVO dto = UserConvertor.INSTANCE.mapToUserVO(user);
        String ipAddress = (String) redisTemplate.opsForValue().get("ip:" + id);
        dto.setAddress(ipAddress);
        return dto;
    }

}
